﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using QuanLyKho.Server;
using QuanLyKho.Server.Dto;
using QuanLyKho.Server.Enum;
using System.Transactions;

namespace QuanLyKho.Server.BLL
{
    public class TonKhoThuocBLL
    {
        public TonKhoThuocBLL()
        {
        }

        /// <summary>
        /// Thực hiện công trừ số lượng tồn kho thuốc
        /// </summary>
        /// <param name="maThuoc"></param>
        /// <param name="soLuong"></param>
        /// <param name="laCong"></param>
        public void CongTruSoLuongTonKhoThuoc(string maThuoc, int soLuong, bool laCong, QuanLyKhoEntities entities)
        {
            TonKhoThuoc tonKhoThuoc = entities.TonKhoThuocs.SingleOrDefault(u => u.MaThuoc == maThuoc);
            if (laCong)
            {
                //Nếu thuốc hiện không có trong CSDL thì add vào dòng mới
                if (tonKhoThuoc == null)
                {
                    tonKhoThuoc = new TonKhoThuoc();
                    tonKhoThuoc.MaThuoc = maThuoc;
                    tonKhoThuoc.SoLuong = soLuong;
                    entities.TonKhoThuocs.Add(tonKhoThuoc);
                    entities.SaveChanges();
                }
                else // Thuốc đã có trong CSDL thực hiện trừ số lượng
                {
                    tonKhoThuoc.SoLuong += soLuong;
                    entities.SaveChanges();
                }
            }
            else
            {
                tonKhoThuoc.SoLuong -= soLuong;
                entities.SaveChanges();
            }
        }

        /// <summary>
        /// Báo cáo thống kê tồn kho thuốc
        /// Tồn kho và tính theo chốt kỳ
        /// </summary>
        /// <param name="maThuoc">mã thuốc</param>
        /// <param name="tuNgay">từ ngày</param>
        /// <param name="denNgay">đến ngày</param>
        /// <returns></returns>
        public List<TonKhoDto> ThongKeTonKho(string maThuoc, DateTime tuNgay, DateTime denNgay)
        {
            tuNgay = Convert.ToDateTime(tuNgay.ToShortDateString() + " 00:00:00");
            denNgay = Convert.ToDateTime(denNgay.ToShortDateString() + " 23:59:59");

            List<TonKhoDto> listDto = new List<TonKhoDto>();

            // Lấy thông tin chốt kỳ gần nhất
            using (QuanLyKhoEntities entities = new QuanLyKhoEntities(QuanLyKhoServerGlobal.ConnectionString))
            {
                ChotSo chotSo = entities.ChotSoes.FirstOrDefault(u => u.NgayChotSo < tuNgay);

                // Truường hợp thống kê lần đầu tiên
                if (chotSo != null)
                {
                    tuNgay = chotSo.NgayChotSo;
                }

                List<TonKhoDto> listNhapXuatDto =
                                (
                                    (
                                    // Tồn đầu kỳ
                                    from d in entities.PhieuNhapThuocChiTiets.Include("PhieuNhapThuoc")
                                                                            .Include("Dm_Thuoc")
                                                                            .Include("Dm_Thuoc.Dm_HamLuong")
                                                                            .Include("Dm_Thuoc.Dm_DonViTinh")
                                    where d.PhieuNhapThuoc.NgayNhap < tuNgay
                                        && (maThuoc.Length == 0 ? true : d.MaThuoc == maThuoc)
                                    group d by new
                                    {
                                        d.MaThuoc,
                                        d.Dm_Thuoc.TenThuoc,
                                        d.Dm_Thuoc.Dm_HamLuong.TenHamLuong,
                                        d.Dm_Thuoc.Dm_DonViTinh.TenDonViTinh,
                                        d.GiaNhap,
                                        d.GiaXuat,
                                        d.PhieuNhapThuoc.ChietKhau,
                                        d.SoLo
                                    } into e
                                    select new TonKhoDto
                                    {
                                        MaThuoc = e.Key.MaThuoc,
                                        TenThuocHamLuong = e.Key.TenThuoc + " " + e.Key.TenHamLuong,
                                        TenDonViTinh = e.Key.TenDonViTinh,
                                        GiaNhap = e.Key.GiaNhap,
                                        GiaXuat = e.Key.GiaXuat,
                                        SoLo = e.Key.SoLo,
                                        SLTonDauKy = e.Sum(u => u.SoLuong),
                                        TTTonDauKy = e.Sum(u => u.SoLuong) * (e.Key.GiaNhap * (100 - e.Key.ChietKhau) / 100),
                                        SLNhapTrongKy = 0,
                                        TTNhapTrongKy = 0,
                                        //SLTongCongDauKy = 0,
                                        //TTTongCongDauKy = 0,
                                        SLXuatTrongKy = 0,
                                        TTXuatTrongKy = 0,
                                        TTXuatVon = 0,
                                        SLTonCuoiKy = 0,
                                        TTTonCuoiKy = 0
                                    }
                                )
                                .Concat
                                (
                                    // Nhập trong kỳ
                                    from d in entities.PhieuNhapThuocChiTiets.Include("PhieuNhapThuoc")
                                                                            .Include("Dm_Thuoc")
                                                                            .Include("Dm_Thuoc.Dm_HamLuong")
                                                                            .Include("Dm_Thuoc.Dm_DonViTinh")
                                    where d.PhieuNhapThuoc.NgayNhap >= tuNgay && d.PhieuNhapThuoc.NgayNhap <= denNgay
                                        && (maThuoc.Length == 0 ? true : d.MaThuoc == maThuoc)
                                    group d by new
                                    {
                                        d.MaThuoc,
                                        d.Dm_Thuoc.TenThuoc,
                                        d.Dm_Thuoc.Dm_HamLuong.TenHamLuong,
                                        d.Dm_Thuoc.Dm_DonViTinh.TenDonViTinh,
                                        d.GiaNhap,
                                        d.GiaXuat,
                                        d.PhieuNhapThuoc.ChietKhau,
                                        d.SoLo
                                    } into e
                                    select new TonKhoDto
                                    {
                                        MaThuoc = e.Key.MaThuoc,
                                        TenThuocHamLuong = e.Key.TenThuoc + " " + e.Key.TenHamLuong,
                                        TenDonViTinh = e.Key.TenDonViTinh,
                                        GiaNhap = e.Key.GiaNhap,
                                        GiaXuat = e.Key.GiaXuat,
                                        SoLo = e.Key.SoLo,
                                        SLTonDauKy = 0,
                                        TTTonDauKy = 0,
                                        SLNhapTrongKy = e.Sum(u => u.SoLuong),
                                        TTNhapTrongKy = e.Sum(u => u.SoLuong) * (e.Key.GiaNhap * (100 - e.Key.ChietKhau) / 100),
                                        //SLTongCongDauKy = 0,
                                        //TTTongCongDauKy = 0,
                                        SLXuatTrongKy = 0,
                                        TTXuatTrongKy = 0,
                                        TTXuatVon = 0,
                                        SLTonCuoiKy = 0,
                                        TTTonCuoiKy = 0
                                    }
                                )
                                .Concat
                                (
                                    // Xuất trong kỳ
                                    from d in entities.PhieuXuatThuocChiTiets.Include("PhieuXuatThuoc")
                                                                            .Include("PhieuNhapThuocChiTiet")
                                                                            .Include("PhieuNhapThuocChiTiet.Dm_Thuoc")
                                                                            .Include("PhieuNhapThuocChiTiet.Dm_HamLuong")
                                                                            .Include("PhieuNhapThuocChiTiet.Dm_DonViTinh")
                                    where d.PhieuXuatThuoc.NgayXuat >= tuNgay && d.PhieuXuatThuoc.NgayXuat <= denNgay
                                        && (maThuoc.Length == 0 ? true : d.PhieuNhapThuocChiTiet.MaThuoc == maThuoc)
                                    group d by new
                                    {
                                        d.PhieuNhapThuocChiTiet.MaThuoc,
                                        d.PhieuNhapThuocChiTiet.Dm_Thuoc.TenThuoc,
                                        d.PhieuNhapThuocChiTiet.Dm_Thuoc.Dm_HamLuong.TenHamLuong,
                                        d.PhieuNhapThuocChiTiet.Dm_Thuoc.Dm_DonViTinh.TenDonViTinh,
                                        d.PhieuNhapThuocChiTiet.GiaNhap,
                                        d.GiaXuat,
                                        d.PhieuNhapThuocChiTiet.SoLo
                                    } into e
                                    select new TonKhoDto
                                    {
                                        MaThuoc = e.Key.MaThuoc,
                                        TenThuocHamLuong = e.Key.TenThuoc + " " + e.Key.TenHamLuong,
                                        TenDonViTinh = e.Key.TenDonViTinh,
                                        GiaNhap = e.Key.GiaNhap,
                                        GiaXuat = e.Key.GiaXuat,
                                        SoLo = e.Key.SoLo,
                                        SLTonDauKy = 0,
                                        TTTonDauKy = 0,
                                        SLNhapTrongKy = 0,
                                        TTNhapTrongKy = 0,
                                        //SLTongCongDauKy = 0,
                                        //TTTongCongDauKy = 0,
                                        SLXuatTrongKy = e.Sum(u => u.SoLuong),
                                        TTXuatTrongKy = e.Sum(u => u.SoLuong) * e.Key.GiaXuat,
                                        TTXuatVon = e.Sum(u => u.SoLuong) * e.Key.GiaNhap,
                                        SLTonCuoiKy = 0,
                                        TTTonCuoiKy = 0
                                    }
                                )
                            ).ToList();

                // Lấy danh sách thuốc
                List<Dm_Thuoc> listDmThuoc = (from a in entities.Dm_Thuoc.Include("Dm_HamLuong").Include("Dm_DonViTinh")
                                              where maThuoc.Length == 0 ? true : a.MaThuoc == maThuoc
                                              select a).ToList();

                // Lặp danh sách danh mục thuốc
                foreach (Dm_Thuoc item in listDmThuoc)
                {
                    List<TonKhoDto> tonKho = (from a in listNhapXuatDto
                                              where a.MaThuoc == item.MaThuoc
                                              group a by new
                                              {
                                                  a.MaThuoc,
                                                  a.TenThuocHamLuong,
                                                  a.TenDonViTinh,
                                                  a.SoLo
                                                  //a.GiaNhap,
                                                  //a.GiaXuat
                                              } into e
                                              select new TonKhoDto
                                              {
                                                  MaThuoc = e.Key.MaThuoc,
                                                  TenThuocHamLuong = e.Key.TenThuocHamLuong,
                                                  TenDonViTinh = e.Key.TenDonViTinh,
                                                  GiaNhap = 0,
                                                  GiaXuat = 0,
                                                  SoLo = e.Key.SoLo,
                                                  SLTonDauKy = e.Sum(u => u.SLTonDauKy),
                                                  TTTonDauKy = e.Sum(u => u.TTTonDauKy),
                                                  SLNhapTrongKy = e.Sum(u => u.SLNhapTrongKy),
                                                  TTNhapTrongKy = e.Sum(u => u.TTNhapTrongKy),
                                                  //SLTongCongDauKy = e.Sum(u => u.SLTonDauKy) + e.Sum(u => u.SLNhapTrongKy),
                                                  //TTTongCongDauKy = e.Sum(u => u.TTTonDauKy) + e.Sum(u => u.TTNhapTrongKy),
                                                  SLXuatTrongKy = e.Sum(u => u.SLXuatTrongKy),
                                                  TTXuatTrongKy = e.Sum(u => u.TTXuatTrongKy),
                                                  TTXuatVon = e.Sum(u => u.TTXuatVon),
                                                  SLTonCuoiKy = e.Sum(u => u.SLTonDauKy) + e.Sum(u => u.SLNhapTrongKy) - e.Sum(u => u.SLXuatTrongKy),
                                                  TTTonCuoiKy = e.Sum(u => u.TTTonDauKy) + e.Sum(u => u.TTNhapTrongKy) - e.Sum(u => u.TTXuatVon)
                                              }).ToList();
                    if (tonKho.Count > 0)
                    {
                        if(chotSo != null)
                        {
                            foreach (TonKhoDto tk in tonKho)
                            {
                                if (LaThuocChotSo(chotSo, tk))
                                { 
                                    tk.SLTonDauKy += chotSo.SLTonDauKy;
                                    tk.TTTonDauKy += chotSo.TTTonDauKy;
                                    tk.SLNhapTrongKy += chotSo.SLNhapTrongKy;
                                    tk.TTNhapTrongKy += chotSo.TTNhapTrongKy;
                                    //tk.SLTongCongDauKy += chotSo.SLTongCongDauKy;
                                    //tk.TTTongCongDauKy += chotSo.TTTongCongDauKy;
                                    tk.SLXuatTrongKy += chotSo.SLXuatTrongKy;
                                    tk.TTXuatTrongKy += chotSo.TTXuatTrongKy;
                                    tk.TTXuatVon += chotSo.TTXuatVon;
                                    tk.SLTonCuoiKy += chotSo.SLTonCuoiKy;
                                    tk.TTTonCuoiKy += chotSo.TTTonCuoiKy;
                                }
                            }
                        }
                        
                        // Thêm danh sách tồn kho có trường hợp nhiều giá xuất khác nhau
                        listDto.AddRange(tonKho);
                    }
                    else
                    {
                        TonKhoDto tk = new TonKhoDto
                        {
                            MaThuoc = item.MaThuoc,
                            TenThuocHamLuong = item.TenThuocHamLuong,
                            TenDonViTinh = item.Dm_DonViTinh.TenDonViTinh,
                            GiaNhap = item.GiaNhap,
                            GiaXuat = item.GiaXuat,
                        };
                        if(chotSo != null)
                        {
                            if(LaThuocChotSo(chotSo, tk))
                            {
                                tk.SLTonDauKy = chotSo.SLTonDauKy;
                                tk.TTTonDauKy = chotSo.TTTonDauKy;
                                tk.SLNhapTrongKy = chotSo.SLNhapTrongKy;
                                tk.TTNhapTrongKy = chotSo.TTNhapTrongKy;
                                //tk.SLTongCongDauKy = chotSo.SLTongCongDauKy;
                                //tk.TTTongCongDauKy = chotSo.TTTongCongDauKy;
                                tk.SLXuatTrongKy = chotSo.SLXuatTrongKy;
                                tk.TTXuatTrongKy = chotSo.TTXuatTrongKy;
                                tk.SLTonCuoiKy = chotSo.SLTonCuoiKy;
                                tk.TTTonCuoiKy = chotSo.TTTonCuoiKy;
                            }
                        }
                        
                        // Trường hợp thuốc chưa nhập xuất
                        listDto.Add(tk);
                    }
                }
            }

            return listDto;
        }

        public bool LaThuocChotSo(ChotSo chotSo, TonKhoDto tonKhoDto)
        {
            //if (chotSo.MaThuoc == tonKhoDto.MaThuoc && chotSo.GiaNhap == tonKhoDto.GiaNhap && chotSo.GiaXuat == tonKhoDto.GiaXuat)
            if (chotSo.MaThuoc == tonKhoDto.MaThuoc && chotSo.SoLo == tonKhoDto.SoLo)
            {
                return true;
            }
            return false;
        }

        /// <summary>
        /// Kiểm tra xem được phép chốt sổ hay không
        /// </summary>
        /// <param name="denNgay">đến ngày so sánh với ngày chốt sổ trước đó</param>
        /// <returns></returns>
        public bool LaDuocPhepChotSo(DateTime denNgay)
        {
            denNgay = Convert.ToDateTime(denNgay.ToShortDateString() + " 23:59:59");
            bool laDuocPhepChotKy = false;
            using (QuanLyKhoEntities entities = new QuanLyKhoEntities(QuanLyKhoServerGlobal.ConnectionString))
            {
                ChotSo chotSo = entities.ChotSoes.OrderByDescending(u => u.NgayChotSo).FirstOrDefault();
                // Trường hợp chưa chốt sổ lần nào
                if (chotSo == null)
                    return true;
                else
                {
                    // Trường hợp đã có chốt sổ nhưng ngày chốt sổ đã là trước đó thì cho phép chốt sổ
                    if (chotSo.NgayChotSo < denNgay)
                    {
                        return true;
                    }
                }
            }
            return laDuocPhepChotKy;
        }

        public bool LaChoPhepXuatNhapKho(DateTime denNgay)
        {
            bool laDuocPhepChotKy = false;
            using (QuanLyKhoEntities entities = new QuanLyKhoEntities(QuanLyKhoServerGlobal.ConnectionString))
            {
                ChotSo chotSo = entities.ChotSoes.OrderByDescending(u => u.NgayChotSo).FirstOrDefault();
                // Trường hợp chưa chốt sổ lần nào
                if (chotSo == null)
                    return true;
                else
                {
                    // Trường hợp đã có chốt sổ nhưng ngày chốt sổ đã là trước đó thì cho phép chốt sổ
                    if (chotSo.NgayChotSo <= denNgay)
                    {
                        return true;
                    }
                }
            }
            return laDuocPhepChotKy;
        }

        public void CapNhatChotSo(DateTime denNgay, DateTime ngayChotSo, List<TonKhoDto> listThongKe)
        {
            denNgay = Convert.ToDateTime(denNgay.ToShortDateString() + " 23:59:59");

            using (TransactionScope trans = new TransactionScope())
            {
                using (QuanLyKhoEntities entities = new QuanLyKhoEntities(QuanLyKhoServerGlobal.ConnectionString))
                {
                    // Cập nhật trạng thái phiếu nhập
                    var listPhieuNhap = entities.PhieuNhapThuocs.Where(u => u.NgayNhap <= denNgay && u.TrangThai == EnumTrangThaiPhieu.ChoPhepChinhSua);
                    foreach (var item in listPhieuNhap)
                    {
                        item.TrangThai = EnumTrangThaiPhieu.DaChotKy;
                    }

                    // Cập nhật trạng thái phiếu xuất
                    var listPhieuXuat = entities.PhieuXuatThuocs.Where(u => u.NgayXuat <= denNgay && u.TrangThai == EnumTrangThaiPhieu.ChoPhepChinhSua);
                    foreach (var item in listPhieuXuat)
                    {
                        item.TrangThai = EnumTrangThaiPhieu.DaChotKy;
                    }

                    // Lấy xóa danh sách chốt kỳ cũ
                    //var listDaChotKy = entities.ChotSoes.Where(u => u.NgayChotSo <= denNgay);

                    // Lưu danh sách chốt kỳ mới
                    foreach (var item in listThongKe)
                    {
                        ChotSo chotSo = new ChotSo();
                        chotSo.MaThuoc = item.MaThuoc;
                        chotSo.SoLo = item.SoLo;
                        chotSo.NgayChotSo = ngayChotSo;
                        chotSo.SLTonDauKy = item.SLTonDauKy;
                        chotSo.TTTonDauKy = item.TTTonDauKy;
                        chotSo.SLNhapTrongKy = item.SLNhapTrongKy;
                        chotSo.TTNhapTrongKy = item.TTNhapTrongKy;
                        chotSo.SLXuatTrongKy = item.SLXuatTrongKy;
                        chotSo.TTXuatTrongKy = item.TTXuatTrongKy;
                        chotSo.TTXuatVon = item.TTXuatVon;
                        chotSo.SLTonCuoiKy = item.SLTonCuoiKy;
                        chotSo.TTTonCuoiKy = item.TTTonCuoiKy;
                        entities.ChotSoes.Add(chotSo);
                    }

                    // Lưu tất cả thông tin trên vào Cơ sở dữ liệu
                    entities.SaveChanges();
                }

                trans.Complete();
            }
        }

        /// <summary>
        /// Thống kê thẻ kho
        /// </summary>
        /// <param name="maThuoc">mã thuốc cần thống kê</param>
        /// <param name="tuNgay">thống kê từ ngày</param>
        /// <param name="denNgay">thống kê đến ngày</param>
        /// <returns></returns>
        public List<TheKhoDto> ThongKeTheKho(string maThuoc, DateTime tuNgay, DateTime denNgay)
        {
            tuNgay = Convert.ToDateTime(tuNgay.ToShortDateString() + " 00:00:00");
            denNgay = Convert.ToDateTime(denNgay.ToShortDateString() + " 23:59:59");

            List<TheKhoDto> listDto = new List<TheKhoDto>();


            // Lấy thông tin chốt kỳ gần nhất
            using (QuanLyKhoEntities entities = new QuanLyKhoEntities(QuanLyKhoServerGlobal.ConnectionString))
            {
                listDto = ((from a in entities.PhieuNhapThuocChiTiets.Include("PhieuNhapThuoc")
                                                                     .Include("PhieuNhapThuoc.Dm_NhaPhanPhoi")
                            where a.MaThuoc == maThuoc
                                    && a.PhieuNhapThuoc.NgayNhap >= tuNgay
                                    && a.PhieuNhapThuoc.NgayNhap <= denNgay
                            select new TheKhoDto
                            {
                                Ngay = a.PhieuNhapThuoc.NgayNhap,
                                SCTNhap = a.PhieuNhapThuoc.SoHoaDon,
                                SCTXuat = "",
                                TenNhaPhanPhoi = a.PhieuNhapThuoc.Dm_NhaPhanPhoi.TenNhaPhanPhoi,
                                SLNhap = a.SoLuong,
                                SLXuat = 0,
                                GhiChu = ""
                            })
                          .Concat
                          (from a in entities.PhieuXuatThuocChiTiets.Include("PhieuNhapThuocChiTiet")
                                                                    .Include("PhieuXuatThuoc")
                           where a.PhieuNhapThuocChiTiet.MaThuoc == maThuoc
                                    && a.PhieuXuatThuoc.NgayXuat >= tuNgay
                                    && a.PhieuXuatThuoc.NgayXuat <= denNgay
                           select new TheKhoDto
                           {
                               Ngay = a.PhieuXuatThuoc.NgayXuat,
                               SCTNhap = "",
                               SCTXuat = "",
                               TenNhaPhanPhoi = "",
                               SLNhap = 0,
                               SLXuat = a.SoLuong,
                               GhiChu = ""
                           })
                          ).OrderBy(u => u.Ngay).ToList();

            }

            return listDto;
        }
    }
}
